﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace devtm.Applications
{


    public class LicenceClient : IApplicationOperationContract
    {

        public static event EventHandler<EventArgs> Logs;

        #region Private
        
        ChannelFactory<IApplicationOperationContract> factory;
        IApplicationOperationContract _service;
        IClientChannel _clientService;

        #endregion



        #region Ctor


        public const string DefaultEndPointConfigurationName = "endPointConfigurationName";


        public LicenceClient()
            : this(DefaultEndPointConfigurationName)
        {
            if (Logs != null)
                Logs(this, new EventArgs());
        }


        public LicenceClient(string endPointConfigurationName)
        {

            factory = new ChannelFactory<IApplicationOperationContract>(endPointConfigurationName);
            factory.Faulted += factory_Faulted;

            CreateChannel();

            if (Logs != null)
                Logs(this, new EventArgs());

        }


        public LicenceClient(IApplicationOperationContract service)
        {

            if (service != null)
                _service = service;

            if (Logs != null)
                Logs(this, new EventArgs());

        }


        #endregion



        #region Methodes

        public ApplicationRegisterModelBack Register(ApplicationRegisterModel model)
        {

            bool etat = false;

            if (Logs != null)
                Logs(this, new EventArgs());

            try
            {
                etat = Open();
                var ret = _service.Register(model);
                return ret;
            }
            catch (Exception)
            {

                if (Logs != null)
                    Logs(this, new EventArgs());

                throw;
            }
            finally
            {
                if (etat)
                    Close();
            }

        }

        public bool LogError(ApplicationErrorModel model)
        {

            bool etat = false;

            if (Logs != null)
                Logs(this, new EventArgs());

            try
            {
                etat = Open();
                var ret = _service.LogError(model);
                return ret;
            }
            catch (Exception)
            {

                if (Logs != null)
                    Logs(this, new EventArgs());

                throw;
            }
            finally
            {
                if (etat)
                    Close();
            }

        }

        public string Informations(ApplicationInformationsModel model)
        {

            bool etat = false;

            if (Logs != null)
                Logs(this, new EventArgs());

            try
            {
                etat = Open();
                var ret = _service.Informations(model);
                return ret;
            }
            catch (Exception)
            {

                if (Logs != null)
                    Logs(this, new EventArgs());

                throw;
            }
            finally
            {
                if (etat)
                    Close();
            }

        }

        #endregion



        #region Utils

        private void CreateChannel()
        {
            if (factory != null)
                if (factory.State != CommunicationState.Opened && factory.State != CommunicationState.Opening)
                {
                    _clientService = ((_service = factory.CreateChannel()) as IClientChannel);
                    _clientService.Faulted += _service2_Faulted;
                }
        }

        private bool Open()
        {

            if (_clientService != null)
                if (_clientService.State != CommunicationState.Opened && _clientService.State != CommunicationState.Opening)
                {

                    if (Logs != null)
                        Logs(this, new EventArgs());

                    _clientService.Open();

                    return true;
                }

            return false;

        }

        private void Close()
        {

            if (_clientService != null && _clientService.State != CommunicationState.Closed && _clientService.State != CommunicationState.Closing)

                try
                {

                    if (Logs != null)
                        Logs(this, new EventArgs());

                    _clientService.Close();

                }
                catch (Exception)
                {
                    _clientService.Abort();
                }
                
        }

        #region Events
        
        void factory_Faulted(object sender, EventArgs e)
        {

            if (Logs != null)
                Logs(this, e);

            Close();
        }

        void _service2_Faulted(object sender, EventArgs e)
        {

            if (Logs != null)
                Logs(this, e);

            Close();
        }

        #endregion

        #endregion

        #region Sessions


        public IDisposable GetSession()
        {
            return new Session(this);
        }


        private class Session : IDisposable
        {

            bool open = false;
            LicenceClient client;
            internal Session(LicenceClient client)
            {

                if (Logs != null)
                    Logs(this, new EventArgs());

                this.client = client;
                open = client.Open();
            }

            public void Dispose()
            {

                if (Logs != null)
                    Logs(this, new EventArgs());

                if (open)
                    client.Close();

            }

        }

        #endregion

    }

}